package com.gzhryc.shared_device.oem.code.user.services;

import java.sql.SQLException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.IDTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.config.DefaultEnum;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.pay.adaptation.weixin.DefaultWXPayConfig;
import com.gzhryc.pay.adaptation.weixin.WXPayTransferMoneyService;
import com.gzhryc.pay.adaptation.weixin.msg.transfer.WXPayTransferMoneyPayResponse;
import com.gzhryc.pay.enums.ReceivingMoneyType;
import com.gzhryc.shared_device.base.enums.ELogState;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.base.models.OrderLogContent;
import com.gzhryc.shared_device.common.payment.dao.db.PayAccountGroup;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayConfig;
import com.gzhryc.shared_device.common.payment.dao.db.WXTransferMoneyOrder;
import com.gzhryc.shared_device.common.payment.dao.models.CashWithdrawalConfig;
import com.gzhryc.shared_device.common.payment.services.PayAccountGroupService;
import com.gzhryc.shared_device.common.payment.services.WXPayConfigService;
import com.gzhryc.shared_device.common.payment.services.WXTransferMoneyOrderService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.order.OrderTradeNoPrefix;
import com.gzhryc.shared_device.oem.code.user.dao.UserTransferMoneyOrderDao;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.code.user.dao.db.UserTransferMoneyOrder;
import com.gzhryc.shared_device.oem.code.user.dao.db.UserTransferMoneyQrcode;
import com.gzhryc.shared_device.oem.code.user.dao.db.UserTransferMoneyWX;
import com.gzhryc.shared_device.oem.code.user.dao.db.UserWallet;
import com.gzhryc.shared_device.oem.code.user.dao.enums.UserTransferMoneyOrderEnum;
import com.gzhryc.shared_device.oem.code.user.dao.enums.UserTransferMoneyQrcodeEnum;
import com.gzhryc.shared_device.oem.code.user.event.UserAutoTransferMoneyEvent;
import com.gzhryc.shared_device.oem.code.user.services.dto.UserTransferMoneyOrderSearch;

public class UserTransferMoneyOrderService {

    static Logger log = Logger.getLogger(UserTransferMoneyOrderService.class);

    public static UserTransferMoneyOrderService self() {
        return MultiDBTools.getService(UserTransferMoneyOrderService.class, true);
    }

    public static UserTransferMoneyOrderService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, UserTransferMoneyOrderService.class, true);
    }

    UserTransferMoneyOrderDao dao;

    public UserTransferMoneyOrderService(String jdbcKey) {
        this.dao = new UserTransferMoneyOrderDao(jdbcKey);
    }

    public List<UserTransferMoneyOrder> findBySearch(UserTransferMoneyOrderSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().sameDay("createDate",search.getCreateDay());
        conditions.desc("createDate");
        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Long countBySearch(UserTransferMoneyOrderSearch search){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().sameDay("createDate",search.getCreateDay());

        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public UserTransferMoneyOrder getByTradeNo(String tradeNo){
        try {
            return dao.getById(tradeNo);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Integer sumTransferMoneyByUserIdAndState(Long userId,Integer state){
        if(userId != null && state != null) {
            Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
            conditions.and().is("userId", userId);
            conditions.and().is("state", state);

            try {
                Long result = dao.sumTransferMoneyByCondition(conditions);
                if(result != null){
                    return result.intValue();
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return 0;
    }
    
    public Integer sumTodayTransferMoneyByUserId(Long userId) {
    	if(userId != null) {
    		Date date = new Date();
    		Date startDate = DateTools.getDayStart(date);
    		Date endDate = DateTools.getDayEnd(date);
    		
            Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
            conditions.and().is("userId", userId);
            conditions.and().not("state", UserTransferMoneyOrderEnum.State.Reject.index());
            conditions.and().ge("createDate", startDate);
            conditions.and().le("createDate", endDate);

            try {
                Long result = dao.sumTransferMoneyByCondition(conditions);
                if(result != null){
                    return result.intValue();
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
    	return 0;
    }

    public boolean checkApply(CashWithdrawalConfig config,Long userId,Integer transferMoney) throws LogicException {
        // 检查提现时间
        boolean flag = false;
        String weekName = "";
        if (config.getMonthStartDay() != null && config.getMonthEndDay() != null) {
            int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
            if (day < config.getMonthStartDay() || day > config.getMonthEndDay()) {
            	throw new LogicException("请在每月" + config.getMonthStartDay() + "号-" + config.getMonthEndDay() + "号提现");
            }
        }

        int week = DateTools.getWeek(new Date());
        if (StringUtils.isNotBlank(config.getCashWithdrawalWeeks())) {
            String[] names = config.getCashWithdrawalWeeks().split(",");
            for (String name : names) {
                if (week == DefaultEnum.Weeks.valueOf(name).index()) {
                    if (StringUtils.isNotBlank(config.getCashWithdrawalTimes())) {
                        String[] times = config.getCashWithdrawalTimes().split(" - ");
                        if (times.length == 2) {
                            Date currentDate = new Date();
                            try {
                                String dateStr = DateFormatUtils.format(currentDate, "yyyy-MM-dd");
                                String startStr = dateStr + " " + times[0];
                                Date startDate = DateUtils.parseDate(startStr, "yyyy-MM-dd HH:mm:ss");
                                String endStr = dateStr + " " + times[1];
                                Date endDate = DateUtils.parseDate(endStr, "yyyy-MM-dd HH:mm:ss");

                                if (startDate.before(currentDate) && endDate.after(currentDate)) {
                                    flag = true;
                                }
                            } catch (ParseException e) {
                                log.error(e.getMessage(), e);
                            }
                        }
                    }
                }
                weekName = weekName + "," + DefaultEnum.Weeks.valueOf(name).note();
            }
            weekName = weekName.substring(1);
        }

        if (!flag) {
        	throw new LogicException("请在" + weekName + "的" + config.getCashWithdrawalTimes() + "提现");
        }
        
        //检查最小金额和最大金额
        if(config.getMinMoney() > transferMoney || config.getMaxMoney() < transferMoney) {
        	throw new LogicException("每次提现" + config.getMinMoneyStr() + "元到" + config.getMaxMoneyStr() + "元以内");
        }
        
        Integer todayMoney = sumTodayTransferMoneyByUserId(userId);
        if(todayMoney >= config.getDayUserMaxMoney()) {
        	throw new LogicException("每人每天只能提现" + config.getDayUserMaxMoneyStr() + "元");
        }
    	return true;
    }
    
    public String apply(Long userId,Integer type,Integer transferMoney,PayAccountGroup payAccountGroup,String openId
    		,Double serviceCharge,OperateInfo operateInfo) throws LogicException {
    	UserWallet userWallet = UserWalletService.self().getByKeys(userId,payAccountGroup.getId());
        if(userWallet.getWithdrawalMoney() < transferMoney){
        	throw new LogicException("金额不足");
        }
        
        String operateNote= "代理提现";
        User user = UserService.self().getById(userId);
        WXTransferMoneyOrder transferMoneyOrder = null;
        UserTransferMoneyQrcode transferMoneyQrcode = null;
        if (ReceivingMoneyType.Account.index().equals(type)) {
            UserTransferMoneyWX wxUser = UserTransferMoneyWXService.self().getByKeys(payAccountGroup.getWxTransferAppId(),openId ,userId);
            if (wxUser != null) {
                if(StringTools.isBlank(wxUser.getNickname()) || StringTools.isBlank(wxUser.getFaceImg())){
                	throw new LogicException("请选择有昵称和头像的微信号提现");
                }
                if(StringTools.isBlank(wxUser.getPhone())){
                	throw new LogicException("请选择绑定手机的微信号提现");
                }
                transferMoneyOrder = new WXTransferMoneyOrder();
                transferMoneyOrder.setAppType(wxUser.getAppType());
                transferMoneyOrder.setAppId(wxUser.getAppId());
                transferMoneyOrder.setOpenId(wxUser.getOpenId());
                transferMoneyOrder.setNickname(wxUser.getNickname());
                transferMoneyOrder.setFaceImg(wxUser.getFaceImg());
                transferMoneyOrder.setName(wxUser.getName());
                transferMoneyOrder.setPhone(wxUser.getPhone());

                operateNote = operateNote + "(微信号)";
            }else{
            	throw new LogicException("未找到微信账号信息");
            }
        }else if(ReceivingMoneyType.Qrcode.index().equals(type)){
            transferMoneyQrcode = UserTransferMoneyQrcodeService.self().getByUserId(user.getId());
            if(transferMoneyQrcode == null){
            	throw new LogicException("未找到用户的提现二维码");
            }
            operateNote = operateNote + "(二维码)";
        }else{
        	throw new LogicException("请选择有效的提现方式");
        }

        UserTransferMoneyOrder applyEntity = new UserTransferMoneyOrder();
        applyEntity.setUserId(userWallet.getUserId());
        applyEntity.setAccountGroupId(userWallet.getAccountGroupId());
        applyEntity.setUserName(user.getName());
        applyEntity.setUserPhone(user.getPhone());
        applyEntity.setMoney(transferMoney);
        applyEntity.setProfitProportion(serviceCharge);
        if (ReceivingMoneyType.Account.index().equals(type)) {
            applyEntity.setPayType(EPayType.WXPay.index());
            applyEntity.setReceivingType(type);

            try {
                if (UserTransferMoneyOrderService.self().add(applyEntity,transferMoneyOrder,userWallet,operateInfo)) {
                	return applyEntity.getTradeNo();
                }
            } catch (LogicException e) {
               throw e;
            }
        }else if (ReceivingMoneyType.Qrcode.index().equals(type)) {
            //二维码提现
            if(UserTransferMoneyQrcodeEnum.Type.WXQrcode.index().equals(transferMoneyQrcode.getType())) {
                applyEntity.setPayType(EPayType.WXPay.index());
            }else if(UserTransferMoneyQrcodeEnum.Type.AliQrcode.index().equals(transferMoneyQrcode.getType())){
                applyEntity.setPayType(EPayType.Alipay.index());
            }
            applyEntity.setReceivingType(type);
            applyEntity.setReceivingQrcode(transferMoneyQrcode.getQrcode());

            try {
                if (UserTransferMoneyOrderService.self().add(applyEntity,userWallet,operateInfo)) {
                    return applyEntity.getTradeNo();
                }
            } catch (LogicException e) {
            	 throw e;
            }
        }
        return null;
    }
    
    public boolean add(UserTransferMoneyOrder order, WXTransferMoneyOrder transferMoneyOrder, UserWallet userWallet,OperateInfo operateInfo) throws LogicException{
        String tradeNo = OrderTradeNoPrefix.USER_TRANSFER_MONEY_ORDER + userWallet.getUserId() + IDTools.getTimestampSecondID();
        order.setTradeNo(tradeNo);
        order.setCreateDate(new Date());

        //计算手续费
        Integer receiptMoney = order.getMoney();
        if(order.getProfitProportion() > 0) {
            receiptMoney = order.getMoney() - NumberTools.proportion(order.getMoney(), order.getProfitProportion());
        }
        order.setReceiptMoney(receiptMoney);

        transferMoneyOrder.setTradeNo(tradeNo);
        transferMoneyOrder.setNote(order.getUserName() + "提现");
        transferMoneyOrder.setMoney(receiptMoney);
        transferMoneyOrder.setCreateDate(order.getCreateDate());

        Long freezeMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(order.getMoney()));

        boolean flag = false;
        JdbcSession.begin();
        try {
            if(dao.insert(order) > 0){
                if(WXTransferMoneyOrderService.self().add(transferMoneyOrder)){
                    if(UserWalletService.self().freezeMoney(userWallet.getUserId(),userWallet.getAccountGroupId(),freezeMoney,operateInfo)){
                        JdbcSession.commit();
                        flag = true;
                    }
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        } finally {
            JdbcSession.end();
        }

        if(flag){
            //记录订单日志
            OrderLogContent.LogItem logItem = new OrderLogContent.LogItem();
            logItem.setCreateDate(new Date());
            logItem.setContent("用户提现申请入库");
            logItem.setState(ELogState.Success.index());
            logItem.setProgramType(operateInfo.getProgramType());
            logItem.setProgramTypeName(operateInfo.getProgramTypeName());
            logItem.setOperatorType(operateInfo.getOperatorType());
            logItem.setOperatorTypeName(operateInfo.getOperatorTypeName());
            logItem.setOperator(operateInfo.getOperator());
            UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),logItem);

            //触发自动转账事件
            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
            if (producer != null) {
                UserAutoTransferMoneyEvent event = new UserAutoTransferMoneyEvent(order.getTradeNo(), null);
                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_UserAutoTransferMoney, JsonTools.toJson(event));
                producer.send(kafkaMessage);
            }else{
                log.error("KafkaProducer为空，自动转账操作失败，订单：{{0}}",order.getTradeNo());
            }

            return true;
        }
        return false;
    }

    public boolean add(UserTransferMoneyOrder order, UserWallet userWallet,OperateInfo operateInfo) throws LogicException{
        String tradeNo = OrderTradeNoPrefix.USER_TRANSFER_MONEY_ORDER + userWallet.getUserId() + IDTools.getTimestampSecondID();
        order.setTradeNo(tradeNo);
        order.setCreateDate(new Date());

        //计算手续费
        Integer receiptMoney = order.getMoney();
        if(order.getProfitProportion() > 0) {
            receiptMoney = order.getMoney() - NumberTools.proportion(order.getMoney(), order.getProfitProportion());
        }
        order.setReceiptMoney(receiptMoney);

        Long freezeMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(order.getMoney()));

        boolean flag = false;
        JdbcSession.begin();
        try {
            if(dao.insert(order) > 0){
                if(UserWalletService.self().freezeMoney(userWallet.getUserId(),userWallet.getAccountGroupId(),freezeMoney,operateInfo)){
                    JdbcSession.commit();
                    flag = true;
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        } finally {
            JdbcSession.end();
        }

        if(flag){
            //记录订单日志
            OrderLogContent.LogItem logItem = new OrderLogContent.LogItem();
            logItem.setCreateDate(new Date());
            logItem.setContent("用户提现申请入库");
            logItem.setState(ELogState.Success.index());
            logItem.setProgramType(operateInfo.getProgramType());
            logItem.setProgramTypeName(operateInfo.getProgramTypeName());
            logItem.setOperatorType(operateInfo.getOperatorType());
            logItem.setOperatorTypeName(operateInfo.getOperatorTypeName());
            logItem.setOperator(operateInfo.getOperator());
            UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),logItem);

            //触发自动转账事件
            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
            if (producer != null) {
                UserAutoTransferMoneyEvent event = new UserAutoTransferMoneyEvent(order.getTradeNo(), null);
                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_UserAutoTransferMoney, JsonTools.toJson(event));
                producer.send(kafkaMessage);
            }else{
                log.error("KafkaProducer为空，自动转账操作失败，订单：{{0}}",order.getTradeNo());
            }

            return true;
        }

        return false;
    }

    /**
     * 驳回提现
     * @param tradeNo
     * @param operateInfo
     * @return
     * @throws LogicException
     */
    public boolean reject(String tradeNo, OperateInfo operateInfo) throws LogicException {
        if(StringTools.isNotBlank(tradeNo)){
            UserTransferMoneyOrder order = getByTradeNo(tradeNo);
            if(order == null){
                throw new LogicException("未找到用户提现订单");
            }
            String logContent = "驳回提现";

            if(!UserTransferMoneyOrderEnum.State.Check.index().equals(order.getState())){
                if(UserTransferMoneyOrderEnum.State.Processing.index().equals(order.getState())){
                    //检查时间
                    Long hour = DateTools.differenceHour(order.getHandleDate(),new Date());
                    if(hour < 3){
                        UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(),"用户提现订单转账中");
                        throw new LogicException("用户提现订单转账中，请3个小时后再处理");
                    }
                }else {
                    throw new LogicException("用户提现订单已处理");
                }
            }
            WXTransferMoneyOrder transferMoneyOrder = null;
            if(EPayType.WXPay.index().equals(order.getPayType())) {
            	transferMoneyOrder = WXTransferMoneyOrderService.self().getByTradeNo(order.getTradeNo());
            }

            Integer logState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
            conditions.and().is("tradeNo", order.getTradeNo());
            conditions.and().is("state", order.getState());

            UserTransferMoneyOrder updateEntity = new UserTransferMoneyOrder();
            updateEntity.setState(UserTransferMoneyOrderEnum.State.Reject.index());
            updateEntity.setHandleType(UserTransferMoneyOrderEnum.HandleType.ManualProcessing.index());
            String operator = "[" + operateInfo.getOperatorTypeName() + "]" + operateInfo.getOperator();
            updateEntity.setOperator(operator);
            updateEntity.setHandleDate(new Date());
            updateEntity.setRejectNote(operateInfo.getOperateNote());

            Long freezeMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(order.getMoney()));

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    if (UserWalletService.self().unfreezeMoney(order.getUserId(), order.getAccountGroupId(),freezeMoney, operateInfo)) {
                    	if(transferMoneyOrder != null) {
                    		WXTransferMoneyOrderService.self().toClose(transferMoneyOrder.getTradeNo(), "提现被驳回");
                    	}
                    	JdbcSession.commit();
                    } else {
                        logState = ELogState.Fail.index();
                        errorMsg = "解冻金额失败";
                        log.error("驳回{{0}}用户提现时解冻金额失败", order.getTradeNo());
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
                logState = ELogState.Fail.index();
                errorMsg = e.getMessage();
            } finally {
                JdbcSession.end();
            }

            UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,logState,errorMsg);
            if(ELogState.Success.index().equals(logState)){
               return true;
            }else {
                throw new LogicException(errorMsg);
            }
        }
        return false;
    }

    /**
     * 下线处理
     * @param tradeNo
     * @param operateInfo
     * @return
     */
    public boolean officeProcessing(String tradeNo,OperateInfo operateInfo)throws LogicException{
        if(StringTools.isNotBlank(tradeNo)) {
            UserTransferMoneyOrder order = getByTradeNo(tradeNo);
            if (order == null) {
                throw new LogicException("未找到用户提现订单");
            }

            if (!UserTransferMoneyOrderEnum.State.Check.index().equals(order.getState())) {
                throw new LogicException("用户提现订单已处理");
            }

            String logContent = "确认下线处理提现";
            Integer logState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
            conditions.and().is("tradeNo", order.getTradeNo());
            conditions.and().is("state", UserTransferMoneyOrderEnum.State.Check.index());

            UserTransferMoneyOrder updateEntity = new UserTransferMoneyOrder();
            updateEntity.setState(UserTransferMoneyOrderEnum.State.Success.index());
            updateEntity.setHandleType(UserTransferMoneyOrderEnum.HandleType.OfflineProcessing.index());
            String operator = "["+operateInfo.getOperatorTypeName()+"]" + operateInfo.getOperator();
            updateEntity.setOperator(operator);
            updateEntity.setHandleDate(new Date());

            Long freezeMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(order.getMoney()));

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    if (UserWalletService.self().reduceFreezeMoney(order.getUserId(),order.getAccountGroupId(), freezeMoney, operateInfo)) {
                        if(ReceivingMoneyType.Account.index().equals(order.getReceivingType())){
                            if(EPayType.WXPay.index().equals(order.getPayType())) {
                                WXTransferMoneyOrderService.self().toClose(order.getTradeNo(), "下线转账");
                            }
                        }
                        JdbcSession.commit();
                    } else {
                        logState = ELogState.Fail.index();
                        errorMsg = "解冻金额失败";
                        log.error("驳回{{0}}用户提现时解冻金额失败", order.getTradeNo());
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }

            UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,logState,errorMsg);
            return ELogState.Success.index().equals(logState);
        }
        return false;
    }

    /**
     * 人工线上处理
     * @param tradeNo
     * @param operateInfo
     * @return
     */
    public boolean manualProcessing(String tradeNo,OperateInfo operateInfo)throws LogicException{
        if(StringTools.isNotBlank(tradeNo)) {
            UserTransferMoneyOrder order = getByTradeNo(tradeNo);
            if (order == null) {
                throw new LogicException("未找到用户提现订单");
            }

            if (!UserTransferMoneyOrderEnum.State.Check.index().equals(order.getState())) {
                throw new LogicException("用户提现订单已处理");
            }

            String logContent = "人工处理用户提现";

            PayAccountGroup payAccountGroup = PayAccountGroupService.self().getById(order.getAccountGroupId());
            if(payAccountGroup == null || !payAccountGroup.getCanTransfer() || StringTools.isBlank(payAccountGroup.getTransferConfig())){
                throw new LogicException("未开启用户提现功能");
            }

            WXPayConfig wxPayConfig = null;
            WXTransferMoneyOrder transferMoneyOrder = null;

            if(ReceivingMoneyType.Account.index().equals(order.getReceivingType())) {
                if (!payAccountGroup.getWxTransfer()) {
                    UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(), "微信转账已关闭");
                    throw new LogicException("微信转账已关闭");
                }
                wxPayConfig = WXPayConfigService.self().getByAppId(payAccountGroup.getWxTransferAppId());
                if (wxPayConfig == null) {
                    UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(), "未找到微信提现账号");
                    throw new LogicException("未找到微信提现账号");
                }
                transferMoneyOrder = WXTransferMoneyOrderService.self().getByTradeNo(order.getTradeNo());
                if(transferMoneyOrder == null){
                    UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(), "未找到微信转账订单");
                    throw new LogicException("未找到微信转账订单");
                }
            }else {
                UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(), "无法线上转账");
                throw new LogicException("无法转账，请下线处理");
            }

            Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
            conditions.and().is("tradeNo", order.getTradeNo());
            conditions.and().is("state", UserTransferMoneyOrderEnum.State.Check.index());

            UserTransferMoneyOrder updateEntity = new UserTransferMoneyOrder();
            updateEntity.setState(UserTransferMoneyOrderEnum.State.Processing.index());
            updateEntity.setHandleType(UserTransferMoneyOrderEnum.HandleType.ManualProcessing.index());
            String operator = "["+operateInfo.getOperatorTypeName()+"]" + operateInfo.getOperator();
            updateEntity.setOperator(operator);
            updateEntity.setHandleDate(new Date());

            boolean flag = false;
            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    flag = true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }

            if(flag) {
                if(wxPayConfig != null && transferMoneyOrder != null) {
                    DefaultWXPayConfig defaultWXPayConfig = ClassTools.copy(new DefaultWXPayConfig(), wxPayConfig);
                    WXPayTransferMoneyService transferMoneyService = new WXPayTransferMoneyService(defaultWXPayConfig);
                    WXPayTransferMoneyPayResponse externalResult = transferMoneyService.applyTransferMoney(transferMoneyOrder);
                    if (externalResult != null) {
                        WXTransferMoneyOrderService.self().updateExternalInfo(order.getTradeNo()
                                , externalResult.getBatch_id(), JsonTools.toJson(externalResult), defaultWXPayConfig.getMchId());
                        return true;
                    }else{
                        UserTransferMoneyOrderLogService.self().add(order.getTradeNo(),operateInfo,logContent,ELogState.Fail.index(), "微信转账请求无返回");
                        WXTransferMoneyOrderService.self().toTransferMoneyFail(order.getTradeNo(),"微信转账请求无返回");
                    }
                }
            }
        }
        return false;
    }

    /**
     * 系统处理转账
     * @return
     */
    public boolean autoProcessing(UserTransferMoneyOrder order,OperateInfo operateInfo) throws LogicException {
        if (!UserTransferMoneyOrderEnum.State.Check.index().equals(order.getState())) {
            throw new LogicException("用户提现订单已处理");
        }

        PayAccountGroup payAccountGroup = PayAccountGroupService.self().getById(order.getAccountGroupId());
        if(payAccountGroup == null || !payAccountGroup.getCanTransfer() || StringTools.isBlank(payAccountGroup.getTransferConfig())){
            throw new LogicException("未开启用户提现功能");
        }

        CashWithdrawalConfig config = JsonTools.fromJson(payAccountGroup.getTransferConfig(),CashWithdrawalConfig.class);
        WXPayConfig wxPayConfig = null;
        WXTransferMoneyOrder transferMoneyOrder = null;

        if (config.getAutoMaxMoney() <= 0) {
            throw new LogicException("自动转账已关闭");
        }
        if (config.getAutoMaxMoney() < order.getMoney()) {
            throw new LogicException("提现超过自动转账金额");
        }

        if (ReceivingMoneyType.Account.index().equals(order.getReceivingType())) {
            if (!payAccountGroup.getWxTransfer()) {
                throw new LogicException("微信转账已关闭");
            }
            wxPayConfig = WXPayConfigService.self().getByAppId(payAccountGroup.getWxTransferAppId());
            if (wxPayConfig == null) {
                throw new LogicException("未找到微信提现账号");
            }
            transferMoneyOrder = WXTransferMoneyOrderService.self().getByTradeNo(order.getTradeNo());
            if (transferMoneyOrder == null) {
                throw new LogicException("未找到微信转账订单");
            }
        } else {
            throw new LogicException("无法自动转账");
        }

        Conditions conditions = new Conditions(UserTransferMoneyOrder.class);
        conditions.and().is("tradeNo", order.getTradeNo());
        conditions.and().is("state", UserTransferMoneyOrderEnum.State.Check.index());

        UserTransferMoneyOrder updateEntity = new UserTransferMoneyOrder();
        updateEntity.setState(UserTransferMoneyOrderEnum.State.Processing.index());
        updateEntity.setHandleType(UserTransferMoneyOrderEnum.HandleType.SysAuto.index());
        String operator = "["+operateInfo.getOperatorTypeName()+"]" + operateInfo.getOperator();
        updateEntity.setOperator(operator);
        updateEntity.setHandleDate(new Date());

        boolean flag = false;

        try {
            if (dao.updateNotNull(updateEntity, conditions) > 0) {
                flag = true;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }

        if (flag) {
            if (wxPayConfig != null && transferMoneyOrder != null) {
                DefaultWXPayConfig defaultWXPayConfig = ClassTools.copy(new DefaultWXPayConfig(), wxPayConfig);
                WXPayTransferMoneyService wxpayV3TransferMoneyService = new WXPayTransferMoneyService(defaultWXPayConfig);
                WXPayTransferMoneyPayResponse externalResult = wxpayV3TransferMoneyService.applyTransferMoney(transferMoneyOrder);
                if (externalResult != null) {
                    WXTransferMoneyOrderService.self().updateExternalInfo(order.getTradeNo()
                            , externalResult.getBatch_id(), JsonTools.toJson(externalResult), defaultWXPayConfig.getMchId());
                    return true;
                } else {
                    WXTransferMoneyOrderService.self().toTransferMoneyFail(order.getTradeNo(), "微信转账请求无返回");
                }
            }
        }
        return false;
    }
}
